<%@import=java.util.Arrays%>
<%@import=java.util.BitSet%>
<%@import=java.util.List%>
<%@import=lpg.util.DispatchWriter%>
<%@main=%>
<%!
    private final DispatchWriter writer;

    private final Control control;
    private final Option option;
    private final Grammar grammar;
    private final Base base;

    %><%@classname%><%(Control control, Base base)
    {
        this.control    = control;
        this.base       = base;

        option          = control.option;
        grammar         = control.grammar;

        setOut(option._syslis);
        writer = option._syslis;
    }

    //
    // PRINT_XREF prints out the Cross-reference map. We build a map from each
    // terminal into the set of items whose Dot-symbol (symbol immediately
    // following the dot ) is the terminal in question.  Note that we iterate
    // backwards over the rules to keep the rules associated with the items
    // sorted, since they are inserted in STACK fashion in the lists:  Last-in,
    // First out.
    //
    void printXref(VariableSymbol[] sortSym, int[] numSymbols, int[] nextItem)
    {
        //
        // First, flush any data left in the report buffer.
        //
        option.flushReport();

        control.printHeading();
        %>

Cross-reference table:
<%
        for (int i = 0; i < grammar.numSymbols; i++)
        {
            int symbol = sortSym[i].symbolIndex();
            if (symbol != grammar.acceptImage && symbol != grammar.eofImage && symbol != grammar.empty)
            {
                %>

<%
                writer.beginAutoWrap();

                %><%=grammar.restoreSymbol(grammar.retrieveString(symbol))%> ==>><%

                writer.setIndentSize(writer.getCurrentColumn() + 1);

                if (grammar.isNonTerminal(symbol))
                {
                    IntArrayList rules = grammar.rulesOfLhs(symbol);
                    for (int k = 0, m = rules.size(); k < m; k++)
                    {
                        %><%=rules.get(k)%><%
                    }
                }
                else
                {
                    for (int itemNo = numSymbols[symbol]; itemNo != Util.NIL; itemNo = nextItem[itemNo])
                    {
                        %><%=base.itemTable[itemNo].ruleNumber%><%
                    }
                }

                writer.endAutoWrap();
            }
        }
        %>

<%
    }

    //
    // PRINT_NON_TERMINAL_FIRST prints the first set for each non-terminal.
    //
    void printNonTerminalFirst(BoundedArray<BitSet> ntFirst)
    {
        //
        // First, flush any data left in the report buffer.
        //
        option.flushReport();

        control.printHeading();
        %>
First map for non-terminals:
<%
        for (int nt = grammar.firstNonTerminal(); nt <= grammar.lastNonTerminal(); nt++)
        {
            %>

<%=grammar.restoreSymbol(grammar.retrieveString(nt))%><%

            writer.beginAutoWrap();
            writer.setIndentSize(4);

            %> ==>><%
            for (int t = grammar.firstTerminal(); t <= grammar.lastTerminal(); t++)
            {
                if (ntFirst.get(nt).get(t))
                {
                    %><%=grammar.restoreSymbol(grammar.retrieveString(t))%><%
                }
            }

            writer.endAutoWrap();
        }
        %>
<%
    }

    //
    // PRINT_FOLLOW_MAP prints the follow map.
    //
    void printFollowMap()
    {
        //
        // First, flush any data left in the report buffer.
        //
        option.flushReport();

        control.printHeading();
        %>
Follow Map:
<%
        for (int nt = grammar.firstNonTerminal(); nt <= grammar.lastNonTerminal(); nt++)
        {
            %>

<%=grammar.restoreSymbol(grammar.retrieveString(nt))%><%

            writer.beginAutoWrap();
            writer.setIndentSize(4);

            %> ==>><%
            for (int t = grammar.firstTerminal(); t <= grammar.lastTerminal(); t++)
            {
                if (base.follow.get(nt).get(t))
                {
                    %><%=grammar.restoreSymbol(grammar.retrieveString(t))%><%
                }
            }

            writer.endAutoWrap();
        }
        %>
<%
    }

    void printSymbolMap(String header, BitSet[] map)
    {
        //
        // First, flush any data left in the report buffer.
        //
        option.flushReport();

        control.printHeading();
        %>
<%=header%>:
<%
        for (int symbol = grammar.firstTerminal(); symbol <= grammar.lastTerminal(); symbol++)
        {
            %>

<%=grammar.restoreSymbol(grammar.retrieveString(symbol))%><%

            writer.beginAutoWrap();
            writer.setIndentSize(4);

            %> ==>><%
            for (int t = grammar.firstTerminal(); t <= grammar.lastTerminal(); t++)
            {
                if (map[symbol].get(t))
                {
                    %><%=grammar.restoreSymbol(grammar.retrieveString(t))%><%
                }
            }

            writer.endAutoWrap();
        }
        %>
<%
    }

    void printRank(List<IntArrayList> sccInRanks, IntArrayList orderedRules, int[] rank)
    {
        if (!sccInRanks.isEmpty())
        {
            %>

Strongly-connected components in ranks:

<%
            for (int i = 0, n = sccInRanks.size(); i < n; i++)
            {
                IntArrayList sccInRanksList = sccInRanks.get(i);
                for (int k = 0, m = sccInRanksList.size(); k < m; k++)
                {
                    %>    <%=grammar.retrieveString(sccInRanksList.get(k))%>
<%
                }
                %>
<%
            }
        }

        %>

RANK RULE
==== ====
<%
        for (int i = 0, n = orderedRules.size(); i < n; i++)
        {
            int ruleNo = orderedRules.get(i);
            %><%=rank[ruleNo]%><%
            writer.padToColumn(5);
            %><%=ruleNo%><%
            writer.padToColumn(10);

            writer.beginAutoWrap();
            %><%=grammar.retrieveString(grammar.rules.get(ruleNo).lhs)%>::=<%
            for (int k = grammar.firstRhsIndex(ruleNo); k < grammar.endRhsIndex(ruleNo); k++)
            {
                int symbol = grammar.rhsSym.get(k);
                %><%=grammar.retrieveString(symbol)%><%
            }
            writer.endAutoWrap();
            %>
<%
        }
    }
%>
